package com.cloudy.cloudspider.search;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Searcher {

    IndexReader[] readers ;
    IndexSearcher[] indexSearchers;
    Map<String ,QueryParser> queryParserMap = new HashMap<>();

    public Searcher(String pre) throws IOException {
        String path = SearcherHelp.getIndexDir(pre);
        File rootFile = new File(path);
        // 获得该文件夹内的所有文件
        File[] array = rootFile.listFiles();

        Set<String> indexDirs = new HashSet<>();
        indexDirs.add(path);
        for (File file:array){
            if(file.isDirectory()){
                if(indexDirs.contains(file.getParent())){
                    indexDirs.remove(file.getParent());
                }
                indexDirs.add(file.getPath());
            }
        }

        int index=0;
        readers = new IndexReader[indexDirs.size()];
        indexSearchers = new IndexSearcher[indexDirs.size()];

        for(String indexDir : indexDirs ) {
            Directory dir = FSDirectory.open(Paths.get(indexDir));
            //通过dir得到的路径下的所有的文件
            readers[index] = DirectoryReader.open(dir);
            //建立索引查询器
            indexSearchers[index] = new IndexSearcher(readers[index]);
            index++;
        }

        //建立查询解析器
        queryParserMap.put("context", new QueryParser("context", SearcherHelp.getAnalyzer()));
        queryParserMap.put("title", new QueryParser("title", SearcherHelp.getAnalyzer()));
        queryParserMap.put("shortContext", new QueryParser("shortContext", SearcherHelp.getAnalyzer()));
    }

    private SearchNewsResult search(String searchQuery) throws IOException, ParseException {
        Set<SearchNewsModel> data = new HashSet<>();
        for(QueryParser queryParser:queryParserMap.values()) {
            Query query = queryParser.parse(searchQuery);
            for(IndexSearcher indexSearcher : indexSearchers ) {
                TopDocs topDocs = indexSearcher.search(query, 10);
                data.addAll(toData(topDocs,indexSearcher));
            }
        }
        return SearchNewsResult.builder().searchNum(data.size()).data(data).build();
    }

    private Set<SearchNewsModel> toData(TopDocs topDocs,IndexSearcher indexSearcher)throws IOException, ParseException {
        Set<SearchNewsModel> data = new HashSet<>();
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document doc = indexSearcher.doc(scoreDoc.doc);
            List<IndexableField> fields =doc.getFields();// field.name() field.stringValue();

            SearchNewsModel model = SearchNewsModel.builder().build();
            for (IndexableField field : fields){
                if(field.name().equalsIgnoreCase("time")){
                    model.setTime(Integer.parseInt(field.stringValue()));
                }else if(field.name().equalsIgnoreCase("title")){
                    model.setTitle(field.stringValue());
                }else if(field.name().equalsIgnoreCase("titleImage")){
                    model.setTitleImage(field.stringValue());
                }else if(field.name().equalsIgnoreCase("context")){
                    model.setContext(field.stringValue());
                }else if(field.name().equalsIgnoreCase("shortContext")){
                    model.setShortContext(field.stringValue());
                }
            }
            data.add(model);
        }
        return data;
    }

    private void close() throws IOException {
        for(IndexReader reader : readers ) {
            reader.close();
        }
    }

    public SearchNewsResult searchKeyword(String keyword) throws Exception {
        long startTime = System.currentTimeMillis();
        SearchNewsResult result = search(keyword);
        long endTime = System.currentTimeMillis();

        result.setSearchTime((endTime - startTime));
        close();
        return result;
    }

    public static void main(String[] args) throws Exception {
        Searcher searcher = new Searcher("toutiao");
        SearchNewsResult result =  searcher.searchKeyword("环球网综合报道");
        System.out.println(" search result :" + GsonHelper.toJson(result));
    }


}

